package cc.telecomdigital.tdstock.Framework.UniqueItem;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;

/** Object for CDR Storage Access **/
public class CDRStorageAccess
{
	public enum IMMEDIATE_SEQ{ TOP, NEXT } 
	
	private final boolean  debugMode = false;
	private final String   LOG_TAG = "CDRStorageAccess";
	
	private Object cdrPrefLock = new Object();
	
	private final String cdrIndexTitle   = "@cdrar@";
	private final String cdrPrefFileName = "@771821668576";
	private final String cdrSeqHeader    = "@cdrAddal";
	//Maximum sequence number for CDR send Seq
	private final  int    	 cdrMaxSeq    = 9999;
	private int           	 cdrSeqNo;
	private SharedPreferences prefObject;	
	
	private List<String> 	highPriorURLList;
	private List<String>     highPriorIDList;
	
	public class CDRSingleStorageObject
	{
		public String idString;
		public String urlString;
		
		public CDRSingleStorageObject(String iIdString, String iUrlString)
		{
			idString  = iIdString;
			urlString = iUrlString;
		}
		
		@Override
		public String toString()
		{
			String string1, string2;
			
			string1 = idString;
			if (string1 == null)
				string1 = "null";
			
			string2 = urlString;
			if (string2 == null)
				string2 = "null";	
			
			return string1 + "," + string2;
		}
		
	}
	
	/** Initialize more like a file storage object for CDR Record
	 *  The file inside contains one-to-one relationship
	 * @param iContext
	 */
	public CDRStorageAccess(Context iContext)
	{
		// a useable file handle
		try
		{
			prefObject = iContext.getSharedPreferences(cdrPrefFileName, Activity.MODE_PRIVATE);
			//Obtain the seqNo from the shelf
			cdrSeqNo = prefObject.getInt(cdrIndexTitle, 0);
		}
		catch(Exception ex)
		{
			cdrSeqNo = 0;
			TDStockLog.e(LOG_TAG, "CDRStorageAccess Exception: " + ex.toString());
		}
		
		if (debugMode)
			TDStockLog.i(LOG_TAG, "CDRStorageAccess start seq: " + cdrSeqNo);
		
		highPriorURLList = new ArrayList<String>();
		highPriorIDList  = new ArrayList<String>();
	}
		
	/** Return the next sequence number will be used for CDR SeqNo
	 * @return int-next Sequence No
	 */
	private int GetNextSeqNo()
	{
		int retSeq;
		
		retSeq = cdrSeqNo;
		++cdrSeqNo;
		if (cdrSeqNo > cdrMaxSeq)
			cdrSeqNo = 0;		
		
		return retSeq;
	}
	
	/** CDR Item are save in a preference file and send thru the file. 
	 *  The input is almost filled in with every thing, except the device Time
	 *  @param iCDRURL - The URL content that have space for dvcTime and seqNo
	 */
	public void AddToCDRFileInfo(String iCDRURL)
	{
		synchronized(cdrPrefLock)
		{
			String                   newString;
			String                   seqString;
			int                      seqNo;
			SharedPreferences.Editor prefEdit;
				
			seqNo = GetNextSeqNo();
			
			//Update our new cdr to file
			prefEdit = prefObject.edit();	
			prefEdit.putInt(cdrIndexTitle, cdrSeqNo);
			
			newString = String.format(iCDRURL, seqNo);			
			//Because our max is 9999, so the count is up to 4 digit
			seqString = String.format("%04d", seqNo);
			prefEdit.putString(cdrSeqHeader + seqString, newString);
			prefEdit.commit();
		}			
	}	
	
	/** Add the CDRRecord to an immediatly, which would be the next for getting.  If there 
	 *  already exist item in the list, it will be push to the back.  It is just a higher priority list.
	 *  @param iCDRURL
	 */
	public void AddToImmediateList(String iCDRURL, IMMEDIATE_SEQ iPos)
	{
		synchronized(cdrPrefLock)
		{
			String                   seqString;
			String                   prefValue;
			String                   prefKey;
			int                      seqNo;			
			SharedPreferences.Editor prefEdit;
				
			//wrap around seqNo
			seqNo = GetNextSeqNo();

			//Because our max is 9999, so the count is up to 4 digit			
			seqString = String.format("%04d", seqNo);			
			//Replace cdr seqNo
			prefKey   = cdrSeqHeader + seqString;			
			prefValue  = String.format(iCDRURL, seqNo);
			
			prefEdit = prefObject.edit();
			prefEdit.putString(prefKey, prefValue);
			
			//Update our new cdr to file
			prefEdit.putInt(cdrIndexTitle, cdrSeqNo);
			prefEdit.commit();
			
			if (iPos == IMMEDIATE_SEQ.TOP)
			{
				highPriorIDList.add(0, prefKey);			
				highPriorURLList.add(0, prefValue);				
			}			
			else
			{
				highPriorIDList.add(prefKey);			
				highPriorURLList.add(prefValue);
			}				
		}		
	}
	
	public boolean HasHighPriorityList()
	{
		if (highPriorIDList.size() == 0)
			return false;
		
		return true;
	}
	
	/** Clear all the save record in the system, more like a restart, 
	 *  however the internal seqNo will not be flushed
	 *  Warning data will not be recovered.
	 */
	public void ClearAllCDRRecord()
	{		
		synchronized(cdrPrefLock)
		{				
			SharedPreferences.Editor prefEdit;
			
			prefEdit = prefObject.edit();			
			prefEdit.clear();
			
			prefEdit.putInt(cdrIndexTitle, cdrSeqNo);			
			prefEdit.commit();
			
			highPriorIDList.clear();
			highPriorURLList.clear();
		}		
	}
		
	/** Remove the CDR Record in the shared preference
	 *  @param iIdString - specificed ID from the record
	 */
	public void RemoveCDRRecord(String iIdString)
	{					
		//Check if it is the one for Index
		if (iIdString.equals(cdrIndexTitle))
			return;
		
		if (debugMode)
			TDStockLog.i(LOG_TAG, "RemoveCDRRecord for " + iIdString);
		
		synchronized(cdrPrefLock)
		{	
			String                   contentValue;
			SharedPreferences.Editor prefEdit;
			int                      index;
			
			contentValue = prefObject.getString(iIdString, null);
			if (contentValue == null)
				return;
			
			if (debugMode)
				TDStockLog.i(LOG_TAG, "RemoveCDRRecord for " + iIdString + " performed.");
			
			try
			{
				index = highPriorIDList.indexOf(iIdString);
				if (index != -1)
				{
					highPriorIDList.remove(index);
					highPriorURLList.remove(index);
				}					
			}
			catch(UnsupportedOperationException ex)
			{
				TDStockLog.e(LOG_TAG, "RemoveCDRRecord UnsupportedOperationException: " + ex.toString());
			}
			
			prefEdit = prefObject.edit();
			prefEdit.remove(iIdString);					
			prefEdit.commit();
		}			
	}
	
	/** With the CDR Content String, you could get the id right away 
	 * @param iCDRURL
	 * @return null or the IDname for the provided URL content
	 */
	public String GetIDName(String iCDRURL)
	{		
		//Maybe this is faster.
		synchronized(cdrPrefLock)
		{	
			int index;
			
			index = highPriorURLList.indexOf(iCDRURL);
			if (index != -1)
				return highPriorIDList.get(index);
			
			Set<String> keySet;
			String      value;
			
			keySet = prefObject.getAll().keySet();
			if ((keySet == null) || (keySet.size() == 0))
				return null;
			
			//remove our index memory
			keySet.remove(cdrIndexTitle);
			
			for (String key : keySet)
			{
				value = prefObject.getString(key, null);
				if (value == null)
					continue;
				if (value.equals(iCDRURL) == true)
				{
					if (debugMode)
						TDStockLog.i(LOG_TAG, "GetIDName for " + iCDRURL + " is " + key);					
					return key;
				}					
			}
		}
		
		if (debugMode)
			TDStockLog.i(LOG_TAG, "GetIDName for " + iCDRURL + " cannot be found.");		
		
		return null;
	}	
	
	/** Get the next Record as an object with require fill-in
	 * @return CDRSingleStorageObject
	 */
	public CDRSingleStorageObject GetNextCDRSendObject()
	{
		synchronized(cdrPrefLock)
		{
			CDRSingleStorageObject newObject;
			
			// This is the higher priority one, we would finish 
			// the higher priority before switching to another one
			if (highPriorURLList.size() != 0)
			{
				newObject =  new CDRSingleStorageObject( highPriorIDList.get(0), 
											      highPriorURLList.get(0));
				if (debugMode)
					TDStockLog.i(LOG_TAG, "GetNextCDRSendObject Priority: " + newObject.toString());
				return newObject;
			}
			
			Set<String>  allKeySet;
			
			//Obtain all the keys
			allKeySet = prefObject.getAll().keySet();
			if (allKeySet == null)
			{
				if (debugMode)
					TDStockLog.i(LOG_TAG, "GetNextCDRSendObject: No extra object");				
				return null;
			}				
			
			allKeySet.remove(cdrIndexTitle);
			if (allKeySet.size() == 0)
			{
				if (debugMode)
					TDStockLog.i(LOG_TAG, "GetNextCDRSendObject: No extra object");
				return null;
			}				
			
			String            urlString;
			ArrayList<String> sortList;
			
			//Sort the list
			sortList = new ArrayList<String>(allKeySet);
			Collections.sort(sortList);		
			allKeySet.clear();
				
			//Get the first key and use the key to get the content
			String  firstKey;
			firstKey = (String)sortList.get(0);			
			urlString = prefObject.getString(firstKey, null);	
			
			newObject =  new CDRSingleStorageObject( firstKey, urlString);
			if (debugMode)
				TDStockLog.i(LOG_TAG, "GetNextCDRSendObject: " + newObject.toString());
			
			return newObject;
			
		}
	}
	
	/** Get the Next Sharesd Preference url
	 * @return urlString */
	public String GetNextCDRSendRecord()
	{	
		String  urlString;
		
		synchronized(cdrPrefLock)
		{		
			// This is the higher priority one, we would finish 
			// the higher priority before switching to another one
			if (highPriorURLList.size() != 0)
			{
				urlString = highPriorURLList.get(0);
				if (debugMode)
					TDStockLog.i(LOG_TAG, "GetNextCDRSendRecord PriorityList: " + urlString);				
				return urlString;
			}
						
			Set<String>  allKeySet;
			
			//Obtain all the keys
			allKeySet = prefObject.getAll().keySet();
			if (allKeySet == null)
				return null;
			
			allKeySet.remove(cdrIndexTitle);
			if (allKeySet.size() == 0)
				return null;
			
			ArrayList<String> sortList;
			
			//Sort the list
			sortList = new ArrayList<String>(allKeySet);
			Collections.sort(sortList);		
			allKeySet.clear();
				
			//Get the first key and use the key to get the content
			String  firstKey;
			firstKey = (String)sortList.get(0);
			urlString = prefObject.getString(firstKey, null);
		}
		
		if (debugMode)
			TDStockLog.i(LOG_TAG, "GetNextCDRSendRecord FirstKey-Value: " + urlString);
		
		return urlString;		
	}		
}
